package org.activequant.data.util.converter;

import org.activequant.calendar.IExchangeCalendar;
import org.activequant.core.domainmodel.data.Candle;
import org.activequant.core.types.TimeFrame;
import org.activequant.core.types.TimeStamp;
import org.activequant.data.retrieval.ISeriesDataIteratorSource;

/**
 * A decorator that changes EOD candle timestamp to the time of the
 * exchange closing, as reported by exchangeCalendar. This is useful when
 * EOD candles have day-only timestamp (time part is 00:00:00), but we want to
 * use these candles for backtesting with other data entities that timestamped
 * realistically (time part is not zero, i.e. within the trading day). Since
 * backtester sorts incoming data stream by timestamp, we better change the
 * EOD candle timestamp to the one of the exchange close time to preserve
 * the correct sequence of data.
 * <p>
 * Use this decorator to wrap candle data source before using it as an input
 * to the MarketDataReplayService.
 * <p>
 * If fetched candles have timeFrame different from TimeFrame.day(), 
 * this decorator does nothing. Therefore, its safe to use it is configurations 
 * when different timeFrames may be requested from backtesting context. <br/>
 * EODCandleIteratorSourceDecorator(extends TransformingIteratorSourceDecorator&lt;Candle&gt;). Holds the following associated variables:
 * <ul>
 * <li>EOD(TimeFrame)(TimeFrame.day())</li>
 * <li>exchangeCalendar(IExchangeCalendar)</li>
 * </ul>
 * Holds the following inherited variables:
 * <ul>
 * <li>source(ISeriesDataIteratorSource&lt;Candle&gt;)</li>
 * <li>timeDelay(long)</li>
 * </ul>
 * @author Mike Kroutikov
 */
public class EODCandleIteratorSourceDecorator extends TransformingIteratorSourceDecorator<Candle> {
	/**
	 * private static final TimeFrame EOD = TimeFrame.day();
	 */
	private static final TimeFrame EOD = TimeFrame.day();
	/**
	 * private final IExchangeCalendar exchangeCalendar;
	 */
	private final IExchangeCalendar exchangeCalendar;
	/**
	 * constructs a EODCandleIteratorSourceDecorator(extends TransformingIteratorSourceDecorator&lt;Candle&gt;) using the given
	 * source(ISeriesDataIteratorSource&lt;Candle&gt;) and exchangeCalendar(IExchangeCalendar) to set its inherited source(ISeriesDataIteratorSource&lt;T&gt;) and
	 * associated exchangeCalendar(IExchangeCalendar)
	 * @param source
	 * @param exchangeCalendar
	 */
	public EODCandleIteratorSourceDecorator(ISeriesDataIteratorSource<Candle> source, IExchangeCalendar exchangeCalendar) {
		super(source);
		this.exchangeCalendar = exchangeCalendar;
	}
	/**
	 * If the given in(Candle) represents 1 Day, it uses the associated exchangeCalendar(IExchangeCalendar) to get the closing time for that day and then sets the timeStamp(TimeStamp)
	 * of the given in(Candle) with that closing time.<br/>
	 * Then it returns the given in(Candle)
	 */
	protected Candle transform(Candle in) {
		if(EOD.equals(in.getTimeFrame())) {
			TimeStamp closeTime = exchangeCalendar.getCloseTimeTodayAsTimeStamp(in.getTimeStamp());
			in.setTimeStamp(closeTime);
		}
		return in;
	}
}
